/***************************************************************************
 *   Copyright (C) 2007 by Grzegorz Latarowski   *
 *   g.latarowski@gmail.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

// local
#include "roi.h"



// ===========================================================================
//                                   GRoi
// ===========================================================================


// ------------------------------ GRoi() -------------------------------------
GRoi::GRoi( QGraphicsItem * pParent, QGraphicsScene * pScene )
	: GGraph( pParent, pScene )
{
	QGraphicsItem::setCursor( QCursor( Qt::ArrowCursor ) );
	
	_color = Qt::gray;
	
	adjust();
}
// ---------------------------------------------------------------------------


// ------------------------------ ~GRoiItem() --------------------------------
GRoi::~GRoi()
{
		// delte all nodes and edges
	foreach( GNode * node, _nodes ) if( node ) delete node;
	foreach( GEdge * edge, _edges ) if( edge ) delete edge;
}
// ---------------------------------------------------------------------------


// ---------------------- GRoi::createNodes() --------------------------------
void GRoi::createNodes( const QPolygonF & positions )
{
		// adjust Roi, called to update _boundingRect to sceneRect()
	adjust();
	
		// clear previous edges
	foreach( GEdge * edge, _edges ) if( edge ) delete edge;
	_edges.clear();
	
		// clear previous nodes
	foreach( GNode * node, _nodes ) if( node ) delete node;
	_nodes.clear();
	
	foreach( QPointF position, positions )
	{
			// create new removable node
		GNode * node = new GNode( this, true );
		node->setToolTip( tr( "Move nodes around the scene to place Roi." ) );
			// set Z Value for node
		node->setZValue( zValue() + 0.02 );
			// set nodes position
		node->setPos( position );
			// add node to scene
		if( scene() ) scene()->addItem( node );
			// add node to rest
		_nodes << node;
	}
	
	updateEdges();
	
		// adjust Roi
	adjust();
}
// ---------------------------------------------------------------------------


// ----------------------- GRoi::nodes() -------------------------------------
QPolygonF GRoi::nodes()const
{
	QPolygonF polygon;
	foreach( GNode * node, _nodes ) if( node ) polygon << node->pos();
	
	return polygon;
}
// ---------------------------------------------------------------------------


// ------------------------ GRoi::updateEdges() ------------------------------
void GRoi::updateEdges()
{
	// clear previous edges
	foreach( GEdge * edge, _edges ) if( edge ) delete edge;
	_edges.clear();
	
	// create edges
	for( int i = 0; i < _nodes.size() - 1; i++ )
	{
		GEdge * edge = new GEdge( this, _nodes[i], _nodes[i+1] );
		edge->setToolTip( tr( "Doubleclick to create new node." ) );
		
			// set Z Value for node
		edge->setZValue( zValue() + 0.01 );
			// add node to scene
		if( scene() ) scene()->addItem( edge );
			// add edge to rest
		_edges << edge;
	}
		// create edge between last and first node
	GEdge * edge = new GEdge( this, _nodes[ _nodes.size() - 1 ], _nodes[0] );
		// set Z Value for node
	edge->setZValue( zValue() + 0.01 );
		// add node to scene
	if( scene() ) scene()->addItem( edge );
	// add edge to rest
	_edges << edge;
}
// ---------------------------------------------------------------------------


// ---------------------------- boundingRect() -------------------------------
QRectF GRoi::boundingRect() const
{
	return _boundingRect;
}
// ---------------------------------------------------------------------------


// ---------------------------- GRoi::setZValue() ----------------------------
void GRoi::setZValue( const qreal z )
{
		// change items z value
	QGraphicsItem::setZValue( z );
		// set for all nodes
	foreach( GNode * node, _nodes ) if( node ) node->setZValue( zValue() + 0.02 );
		// set for all edges
	foreach( GEdge * edge, _edges ) if( edge ) edge->setZValue( zValue() + 0.01 );
}
// ---------------------------------------------------------------------------


// ----------------------------- paint() -------------------------------------
void GRoi::paint( QPainter * pPainter,
				  const QStyleOptionGraphicsItem * pOption,
				  QWidget * widget )
{
	Q_UNUSED( pOption );
	Q_UNUSED( widget );
	
	pPainter->setPen( QPen( Qt::NoPen ) );
	pPainter->setBrush( QColor( 150, 150, 150, 125 ) );

		// paint roi region outer 
	QPainterPath pathRoi;
	pathRoi.addRect( _boundingRect );
	pathRoi.moveTo( _roi.first() );
	pathRoi.addPolygon( _roi );
	pathRoi.closeSubpath();
	
	pPainter->drawPath( pathRoi );
}
// ---------------------------------------------------------------------------


// --------------------------- adjust() --------------------------------------
void GRoi::adjust()
{
	if( scene() ) _boundingRect = scene()->sceneRect();
	
	removeFromIndex();
	_roi.clear();
	foreach( GNode * node, _nodes ) if( node ) _roi << node->pos();
	addToIndex();
	
		// adjust edges
	foreach( GEdge * edge, _edges ) if( edge ) edge->adjust();
	
	update();
}
// ---------------------------------------------------------------------------


// --------------------------- GRoi::removeNode() ----------------------------
void GRoi::removeNode( GNode * node )
{
	if( node )
	{
		int index = _nodes.indexOf( node );
		_nodes.remove( index );
		delete node;
	}
	updateEdges();
	
		// prevent removing to less than 3 nodes, set nodes flag
	if( _nodes.size() < 4 )
		foreach( GNode * node, _nodes ) node->setRemovable( false );
	
	adjust();
}
// ---------------------------------------------------------------------------


// ------------------------- GRoi::addNode() ---------------------------------
void GRoi::addNode( GNode * previousNode, const QPointF & position )
{
	if( previousNode )
	{
			// create new removable node
		GNode * node = new GNode( this );
			// set Z Value for node
		node->setZValue( zValue() + 0.02 );
			// set nodes position
		node->setPos( position );
			// add node to scene
		if( scene() ) scene()->addItem( node );
			// add node to rest, after previousNode
		int index = _nodes.indexOf( previousNode ) + 1;
		_nodes.insert( index, node );
		
		updateEdges();
		
			// update nodes removable flag
		if( _nodes.size() > 3 )
			foreach( GNode * node, _nodes ) node->setRemovable( true );
		else
			foreach( GNode * node, _nodes ) node->setRemovable( false );
		
		adjust();
	}
}
// ---------------------------------------------------------------------------


// ------------------------- GRoi::roiRegion() -------------------------------
QPainterPath GRoi::roiRegion()const
{
	QPainterPath pathRoi;
	pathRoi.moveTo( _roi.first() );
	pathRoi.addPolygon( _roi );
	pathRoi.closeSubpath();
	
	return pathRoi;
}
// ---------------------------------------------------------------------------



// eof
